package main

import "fmt"

func main() {
	//defaultEmptyInterfaceValue()
	//emptyInterfaceType()
	//useOneInterface()
	//useAnyInterface()
	//sliceInterface()
	useInterfaceType()
}

func defaultEmptyInterfaceValue() {
	// 每一个接口都包含两个属性，一个是值，一个是类型
	// 而对于空接口来说，这两都是nil
	var i interface{}
	fmt.Printf("type: %T, value: %v", i, i)
}

// 1.我们通常使用空接口作为类型声明一个实例，而这个实例可以承载任意类型的值
func emptyInterfaceType() {
	// 声明一个空接口实例
	var i interface{}

	// 存int没有问题
	i = 1
	fmt.Println(i)

	// 存字符串也没问题
	i = "hello"
	fmt.Println(i)

	// 存布尔值也没有问题
	i = false
	fmt.Println(i)
}

// 2.接收一个任意类型的参数
func receiveOneInterface(face interface{}) {
	fmt.Println(face)
}

func useOneInterface() {
	a := 10
	b := "hello"
	c := true
	receiveOneInterface(a)
	receiveOneInterface(b)
	receiveOneInterface(c)
}

// 3.接收任意个任意类型的值
func receiveAnyInterface(faces ...interface{}) {
	for _, face := range faces {
		fmt.Println(face)
	}
}

func useAnyInterface() {
	a := 10
	b := "hello"
	c := true
	receiveAnyInterface(a, b, c)
}

// 4.也可以定义任意接收任意类型的空接口，例如，array、slice、map、struct，下面是一个切片的例子：
func sliceInterface() {
	a := make([]interface{}, 5)
	a[0] = 11
	a[1] = "hello world"
	a[2] = []int{11, 22, 33, 44}
	for _, value := range a {
		fmt.Println(value)
	}
}

/*
*
空接口的坑：
1.空接口可以承接任意类型值，但不代表任意类型值就可以承接空接口的值
2.当空接口承接数组和切片后，该对象无法再进行切片
3.当你使用空接口承载值时，它的静态类型是interface{},但动态类型是不知道的
（是int还是string还是其他类型）我们并不知道，因此需要使用类型断言
*/
func interfaceType(i interface{}) {
	switch i.(type) {
	case int:
		fmt.Println("参数类型是int")
	case string:
		fmt.Println("参数类型是string")
	default:
		fmt.Println("unknown type")
	}
}

func useInterfaceType() {
	a := 10
	b := "string"
	interfaceType(a)
	interfaceType(b)
}
